<?php
if(!isset($_REQUEST['errors']))
error_reporting(NULL);
else
error_reporting(E_ALL);

define("IMAGE_BORDER", 10);
define("IMAGE_BORDER_LEFT", 60);
define("IMAGE_BORDER_BOTTOM", 40);
// Number of recent days to graph data for. (0 = all)
define("GRAPH_DAYS", isset($_GET['d']) ? $_GET['d'] : 0 );

$image_width  = 640;
$image_height = 480;

$this->api->get_history();


if(GRAPH_DAYS)
	$this->api->history = array_slice($this->api->history, -GRAPH_DAYS);



if(!function_exists("imagepng")) {
	die("Sorry, this PHP installation cannot create dynamic PNG images");
}

header("Content-type: image/png");
header("Content-disposition: inline; filename=\"Internode_Usage_Graph_".strftime("%Y%m%d").".png\"");

// Make the graph WIDER if need be.
if( count($this->api->history) > $image_width )
	$g_width = count($this->api->history);
else
	$g_width = $image_width;

// Find scale maximum.
//
$max = 0;
$total = 0;
for($i = 0; $i < count($this->api->history); $i++) {
	if($this->api->history[$i]['usage'] > $max)
		$max = $this->api->history[$i]['usage'];
	$total += $this->api->history[$i]['usage'];
}



// Create image of specified size (and leave space for the borders) and a graph image.
$graph = imagecreatetruecolor( $g_width, $image_height );

// And graph colours.
//
$gwhite = imagecolorallocate($graph, 255,255,255);
$red = imagecolorallocate($graph, 224,0,0);
$green = imagecolorallocate($graph, 0,204,0);
$purple = imagecolorallocate($graph, 204,0,204);
$yellow = imagecolorallocate($graph, 255,255,0);
$gblue = imagecolorallocate($graph, 0,0,204);
$gorange = imagecolorallocate($graph, 153,153,0);

imagefill( $graph, 0, 0, imagecolorallocate($graph, 200,200,200) );

// Calculate bar width.
//
if(!GRAPH_DAYS || (GRAPH_DAYS > $this->api->history) )
	$dx = 1;
else
	$dx = ( $image_width - IMAGE_BORDER * 2 ) / (count($this->api->history)+1);


// Draw usage bars and x axis.
// When usage is NEGATIVE, draw bar UP anyway but in yellow.
//
imageantialias($graph, true);
imagesetthickness($graph, 5);

$prev_avg_w = 0;
$prev_avg_m = 0;
for($i = 0; $i < count($this->api->history); $i++)
{
	if($this->api->history[$i]['usage'] > 0)
	{
		$y = $this->api->history[$i]['usage'] * $image_height / $max;
		imagefilledrectangle($graph, ($i*$dx), ($image_height-$y), ($i*$dx)+$dx, $image_height, $green);
	}
	else
	{
		//if(isset($_REQUEST['errors'])) var_dump(array("this->api->history[$i]" => $this->api->history[$i], 'image_height' => $image_height, 'max' => $max));
		$y = (abs($this->api->history[$i]['usage'])) * ($image_height) / $max;
		imagefilledrectangle($graph, ($i*$dx), ($image_height-$y), ($i*$dx)+$dx, $image_height, $yellow);
	}
	
	// Add weekly moving average.
	if($i > 0)
	{
		$avg_w = 0;
		$k_w = 0;
		for($j = ($i-5); $j <= ($i); $j++)
		{
			if( isset($this->api->history[$j]) )
			{
				$avg_w += abs($this->api->history[$j]['usage']);
				$k_w++;
			}
		}
		$avg_w /= $k_w;
		$avg_w_y = $avg_w * $image_height / $max;
		$prev_avg_w_y = $prev_avg_w * $image_height / $max;
		imageline($graph, ($i-0.5)*$dx, ($image_height-$prev_avg_w_y), ($i+0.5)*$dx, ($image_height-$avg_w_y), $purple);
		$prev_avg_w = $avg_w;
		$avg_w = 0;
		$k_w = 0;
	}
	
	// Add quarterly moving average.
	if($i > 0)
	{
		$avg_m = 0;
		$k_m = 0;
		for($j = ($i-30); $j <= ($i); $j++)
		{
			if( isset($this->api->history[$j]) )
			{
				$avg_m += abs($this->api->history[$j]['usage']);
				$k_m++;
			}
		}
		$avg_m /= $k_m;
		$avg_m_y = $avg_m * $image_height / $max;
		$prev_avg_m_y = $prev_avg_m * $image_height / $max;
		imageline($graph, ($i-0.5)*$dx, ($image_height-$prev_avg_m_y), ($i+0.5)*$dx, ($image_height-$avg_m_y), $red);
		$prev_avg_m = $avg_m;
		$avg_m = 0;
		$k_m = 0;
	}
}

imagesetthickness($graph, 1);

// Add overall average.
$y = ($total / count($this->api->history)) * ($image_height) / $max;
imagedashedline($graph, 0, ($image_height-$y), $g_width, ($image_height-$y), $gblue);

// Add remaining daily average.
$y = ($this->api->quota_remaining/$this->api->days_remaining) * ($image_height) / $max;
imagedashedline($graph, 0, ($image_height-$y), $g_width, ($image_height-$y), $gorange);


//if(!isset($_REQUEST['errors']))
//	imagepng($graph);	unset( $graph );	exit;







// And last of all, our temporary resized graph.
//
$resized = imagecreatetruecolor( $image_width, $image_height-IMAGE_BORDER_BOTTOM-(2*IMAGE_BORDER) );



// Graph done. Resize it to target.
//

imagecopyresampled( $resized, $graph, 0, 0, 0, 0, $image_width-(2*IMAGE_BORDER), $image_height-IMAGE_BORDER_BOTTOM-(2*IMAGE_BORDER), $g_width, $image_height );
unset( $graph );


imagepng($resized); unset( $resized ); exit;




// Create image of specified size (and leave space for the borders) and a graph image.
//
$im = imagecreatetruecolor( $image_width + (2*IMAGE_BORDER) + IMAGE_BORDER_LEFT, $image_height + (2*IMAGE_BORDER) + IMAGE_BORDER_BOTTOM );
imagefill( $im, 0, 0, imagecolorallocate($im, 220,220,220) );

// Allocate some colours.
//
$white = imagecolorallocate($im, 255,255,255);
$black = imagecolorallocate($im, 0,0,0);
$darkgreen = imagecolorallocate($im, 0, 102,0);
$blue = imagecolorallocate($im, 0,0,204);
$orange = imagecolorallocate($im, 153,153,0);

// Draw three dashed background lines.
//
$dy = ($image_height-(2*IMAGE_BORDER)-IMAGE_BORDER_BOTTOM)/4;
for($i = 1; $i < 4; $i++) {
	imagedashedline($im, IMAGE_BORDER_LEFT+IMAGE_BORDER, IMAGE_BORDER+($i*$dy), $image_width+IMAGE_BORDER_LEFT-IMAGE_BORDER, IMAGE_BORDER+($i*$dy), $black);
}

// Find where we need to right-align the y axis.
//
$len_max = imagefontwidth(2) * (1+(strlen(sprintf("%.1f Mb", $max))));
$len_mmt = imagefontwidth(2) * (1+(strlen(sprintf("%.1f Mb", ($max*3/4)))));
$len_med = imagefontwidth(2) * (1+(strlen(sprintf("%.1f Mb", ($max/2)))));
$len_mmb = imagefontwidth(2) * (1+(strlen(sprintf("%.1f Mb", ($max/4)))));
$len_min = imagefontwidth(2) * (1+(strlen("0.0 Mb")));
$len_date = imagefontwidth(2) * (1+(strlen( strftime("%d %b %y", $this->api->history[count($this->api->history)]['date']))));

// Draw scale figures on y axis.
//
imagestring($im, 2, IMAGE_BORDER_LEFT+IMAGE_BORDER-$len_max, IMAGE_BORDER-(imagefontheight(2)/2), sprintf("%.1f Mb", $max), $black);
imagestring($im, 2, IMAGE_BORDER_LEFT+IMAGE_BORDER-$len_mmt, IMAGE_BORDER+$dy-(imagefontheight(2)/2), sprintf("%.1f Mb", ($max*3/4)), $black);
imagestring($im, 2, IMAGE_BORDER_LEFT+IMAGE_BORDER-$len_med, IMAGE_BORDER+(2*$dy)-(imagefontheight(2)/2), sprintf("%.1f Mb", ($max/2)), $black);
imagestring($im, 2, IMAGE_BORDER_LEFT+IMAGE_BORDER-$len_mmb, IMAGE_BORDER+(3*$dy)-(imagefontheight(2)/2), sprintf("%.1f Mb", ($max/4)), $black);
imagestring($im, 2, IMAGE_BORDER_LEFT+IMAGE_BORDER-$len_min, $image_height-IMAGE_BORDER_BOTTOM-IMAGE_BORDER-(imagefontheight(2)/2), "0.0 Mb", $black);

// This needs to be twiddled if we have more history than space to draw in...
// First, save the entire history array (for the stats, which we draw later)


// Find out the interval for x axis labels - need to redo this.
//
$mod = intval(count($this->api->history)/8);

$dlx = ( $image_width - IMAGE_BORDER * 2 ) / (count($this->api->history)+1);

for($i = 0; $i < count($this->api->history); $i++)
if($i % $mod == 0)
	imagestringup($im, 2, IMAGE_BORDER_LEFT+IMAGE_BORDER+($i*$dlx)-(imagefontheight(2)/2)+($dlx/2), $image_height-IMAGE_BORDER-IMAGE_BORDER_BOTTOM+$len_date, strftime("%d %b %y", $this->api->history[$i]['date']), $black);









// Add it to output. Merging at 75% transparency seems to make it all look nice.
//
imagecopymerge( $im, $resized, IMAGE_BORDER_LEFT+IMAGE_BORDER, IMAGE_BORDER, 0, 0, $image_width-(IMAGE_BORDER*2), $image_height-IMAGE_BORDER_BOTTOM-(2*IMAGE_BORDER), 75 );
unset( $resized );







// Add some info/legend.
$string = $string = sprintf("Current period: %s - %s", strftime("%a %d %b %Y", $this->api->p_start), strftime("%a %d %b %Y", $this->api->p_end) );
imagestring($im, 2, IMAGE_BORDER_LEFT+IMAGE_BORDER+imagefontwidth(2), (imagefontheight(2) * 1), $string, $black);

if(!$this->api->unlimited)
{
	$string = $string = sprintf("Graph Interval: %d days   Remaining: %d days", count($this->api->history), $this->api->days_remaining);
	imagestring($im, 2, IMAGE_BORDER_LEFT+IMAGE_BORDER+imagefontwidth(2), (imagefontheight(2) * 2), $string, $blue);
	
	$string = sprintf("Daily Transfer: %.1f Mb   Total Transfer: %.1f Gb", ($total / count($this->api->history)), $total/1000);
	imagestring($im, 2, IMAGE_BORDER_LEFT+IMAGE_BORDER+imagefontwidth(2), (imagefontheight(2) * 3), $string, $darkgreen);
	
	if($this->api->quota_remaining > 0)
	{
		$string = sprintf("Daily Remaining: %.1f Mb   Total Remaining: %.1f Gb", ($this->api->quota_remaining / $this->api->days_remaining), ($this->api->quota_remaining/1000) );
		imagestring($im, 2, IMAGE_BORDER_LEFT+IMAGE_BORDER+imagefontwidth(2), (imagefontheight(2) * 4), $string, $orange);
	}
	else
	{
		$over = abs($this->remaining);
		if($over > (1000 * 1000 * 1000 * 1000 * 1000 * 1000 * 1000))
		{
			$over /= (1000 * 1000 * 1000 * 1000 * 1000 * 1000);
			$unit = "Yottabytes";
		}
		else if($over > (1000 * 1000 * 1000 * 1000 * 1000 * 1000))
		{
			$over /= (1000 * 1000 * 1000 * 1000 * 1000);
			$unit = "Zettabytes";
		}
		else if($over > (1000 * 1000 * 1000 * 1000 * 1000))
		{
			$over /= (1000 * 1000 * 1000 * 1000);
			$unit = "Exabytes";
		}
		else if($over > (1000 * 1000 * 1000 * 1000))
		{
			$over /= (1000 * 1000 * 1000);
			$unit = "Petabytes";
		}
		else if($over > (1000 * 1000 * 1000))
		{
			$over /= (1000 * 1000);
			$unit = "Tb";
		}
		else if($over > (1000 * 1000))
		{
			$over /= 1000;
			$unit = "Gb";
		}
		else
		{
			$unit = "Mb";
		}
		$string = sprintf("WARNING: You are %.1f %s over quota!", $over, $unit );
		imagestring($im, 2, IMAGE_BORDER_LEFT+IMAGE_BORDER+imagefontwidth(2), (imagefontheight(2) * 4), $string, $red);
	}
}
else
{
	$string = $string = sprintf("Graph Interval: %d days", count($this->api->history));
	imagestring($im, 2, IMAGE_BORDER_LEFT+IMAGE_BORDER+imagefontwidth(2), (imagefontheight(2) * 2), $string, $blue);
	
	$string = sprintf("Daily Transfer: %.1f Mb   Total Transfer: %.1f Gb", ($total / count($this->api->history)), $total/1000);
	imagestring($im, 2, IMAGE_BORDER_LEFT+IMAGE_BORDER+imagefontwidth(2), (imagefontheight(2) * 3), $string, $darkgreen);
}

// $string = sprintf("Graph: %d days   Daily Average: %.1f Mb   Total: %.1f Gb", count($this->api->history), ($total / count($this->api->history)), $total/1000);
// imagestring($im, 2, IMAGE_BORDER_LEFT+IMAGE_BORDER+imagefontwidth(2), imagefontheight(2), $string, $blue);

// $string = sprintf("Remaining: %d days   Daily Remaining: %.1f Mb   Total Remaining: %.1f Gb", ($this->days_remaining), ($this->remaining / $this->days_remaining), ($this->remaining/1000) );
// imagestring($im, 2, IMAGE_BORDER_LEFT+IMAGE_BORDER+imagefontwidth(2), (imagefontheight(2) * 2), $string, $blue);

// Draw 0-max border around the graph.
//
imageline($im, IMAGE_BORDER_LEFT+IMAGE_BORDER, IMAGE_BORDER, $image_width+IMAGE_BORDER_LEFT-IMAGE_BORDER, IMAGE_BORDER, $black);
imageline($im, IMAGE_BORDER_LEFT+IMAGE_BORDER, IMAGE_BORDER, IMAGE_BORDER_LEFT+IMAGE_BORDER, $image_height-IMAGE_BORDER_BOTTOM-IMAGE_BORDER, $black); 
imageline($im, $image_width+IMAGE_BORDER_LEFT-IMAGE_BORDER, IMAGE_BORDER, $image_width+IMAGE_BORDER_LEFT-IMAGE_BORDER, $image_height-IMAGE_BORDER_BOTTOM-IMAGE_BORDER, $black); 
imageline($im, IMAGE_BORDER_LEFT+IMAGE_BORDER, $image_height-IMAGE_BORDER_BOTTOM-IMAGE_BORDER, $image_width+IMAGE_BORDER_LEFT-IMAGE_BORDER, $image_height-IMAGE_BORDER_BOTTOM-IMAGE_BORDER, $black);

// And now just add a footer.
//
$footer = sprintf("PADSL usage graph %s - %s for %s@internode.on.net", strftime("%d/%m/%Y", $this->api->history[0]['date']), strftime("%d/%m/%Y", $this->api->history[count($this->api->history)-1]['date']), $this->api->username );
imagestring($im, 3, (IMAGE_BORDER_LEFT+$image_width+(2*IMAGE_BORDER))/2 - imagefontwidth(3) * (strlen($footer)/2), $image_height+IMAGE_BORDER_BOTTOM-IMAGE_BORDER, $footer, $black);

$copyright = sprintf("Generated by internode.php v.%d - Copyright 2004 - 2007 Intellectual Property Holdings Pty. Ltd.", $this->api->internode_version );
imagestring($im, 1, (IMAGE_BORDER_LEFT+$image_width+(2*IMAGE_BORDER))/2 - imagefontwidth(1) * (strlen($copyright)/2), $image_height+IMAGE_BORDER_BOTTOM+IMAGE_BORDER, $copyright, $black);

// Output image and deallocate memory.
//
if(!isset($_REQUEST['errors']))
	imagepng($im);
imagedestroy($im);
